package com.kx.ssm.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.kx.ssm.constants.ResultCode;
import com.kx.ssm.exception.AddDataException;
import com.kx.ssm.exception.QueryDataException;
import com.kx.ssm.exception.UpdateDataException;
import com.kx.ssm.mapper.UserMapper;
import com.kx.ssm.pojo.User;
import com.kx.ssm.service.UserService;
import com.kx.ssm.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @ClassName UserServiceImpl
 * @Author Sun
 * @Date 2021/5/20 22:28
 */
@Service
@Transactional  //事务管理
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public PageInfo<User> getUsersByPage(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<User> users = userMapper.findAllUsers();
        //通过遍历挨个删除密码和盐
        users.stream().forEach(user->{user.setPassword(null);user.setPasswordsalt(null);});
        PageInfo<User> pageInfo = new PageInfo<>(users);
        return pageInfo;
    }

    @Override
    public User getUserById(Long id) {
        User user = userMapper.getUserById(id);
        if (user == null) {
            throw new QueryDataException("数据不存在", ResultCode.ID_NOT_EXIST);
        }
        return user;
    }

    @Override
    public void addUser(User user) {
        //这个 user 可能是空的,还有个可能 数据不全
        if (user == null || user.isEmpty()) {
            throw new AddDataException("添加的用户信息不全", ResultCode.DATA_NOT_WANZHENG);
        }

        //更新用户的密码
        //需要加盐, 盐能用一样的吗? 每个用户理论上盐不一样,所以表中还需要保存盐
        //加密的时候我们可以加多次,比如说循环 2048 次

        //对密码进行加盐处理，使用编写的StringUtils工具类获取指定长度随机数作为盐
        String passwordSalt = StringUtils.getRandomString(10);
        user.setPasswordsalt(passwordSalt);
        //对密码进行MD5加密
        String md5Password = StringUtils.getMd5(user.getPassword(), passwordSalt, 2048);
        user.setPassword(md5Password);
        userMapper.addUser(user);
    }

    @Override
    public User findUserByNameAndPassword(User user) {
        if (user == null || StringUtils.isEmpty(user.getUsername()) || StringUtils.isEmpty(user.getPassword())) {
            throw new QueryDataException("用户名或密码错误", ResultCode.USERNAME_PASSOWRD_ERROR);
        }
        //我们现在用户传递过来的密码是明文,需要转换为 md5,用不了,因为盐需要先查出来
        //或者先用用户名查询,查询出来再比较密码,而且用户名是唯一的,本身有索引,查询速度会相对起来比较快
        User userByUserName = userMapper.findUserByUserName(user.getUsername());//数据库中保存的用户信息
        if (userByUserName != null) {
            //获取该用户数据库中存储的密码
            String dbPassword = userByUserName.getPassword();
            //获取该用户数据库中存储的密码的盐
            String passwordSalt = userByUserName.getPasswordsalt();
            //将密码转成MD5格式
            String md5PassWord = StringUtils.getMd5(user.getPassword(), passwordSalt, 2048);
            if (dbPassword.equals(md5PassWord)) {
                //用户名密码是对的
                userByUserName.setPassword(null);//将用户的密码设置 null,防止因为某些原因不小心展示到页面上
                return userByUserName;
            }
        }
        //用户不存在,或者是用户名密码错误
        throw new QueryDataException("用户名或密码错误", ResultCode.USERNAME_PASSOWRD_ERROR);
    }

    @Override
    public void updateUser(User user) {
        if (user.getId() == null || user.getId() == 0) {
            throw new UpdateDataException("用户不存在", ResultCode.ID_NOT_EXIST);
        }
        //session中包括用户的所有信息，除了密码
        //用户更新的时候可能会更新密码,所以要重新计算 MD5 值,但是问题来了,因为你不知道用户有没有改密码
        //user信息中没有password不为空说明用户需要更新密码
        if (!StringUtils.isEmpty(user.getPassword())) {
            //需要更新密码，表单中带过来的json数据中密码不是加密的，所有需要重新计算MD5值
            user.setPassword(StringUtils.getMd5(user.getPassword(), user.getPasswordsalt(), 2048));
        }

        userMapper.updateUser(user);

    }


    @EventListener
    @Override
    public void onEvent(User user) {
        System.err.println("收到更新用户的操作了");
        userMapper.updateUser(user);
    }
}
